import dbus
from dbus.mainloop.glib import DBusGMainLoop
import time
import argparse

# Values returned by the callback
ONLINE, OFFLINE, UNKNOWN = object(), object(), object()

NM_STATE_NAMES = {
    ONLINE: "online",
    OFFLINE: "offline",
    UNKNOWN: "unknown",
}

# Internal NetworkManager State constants
NM_STATE_UNKNOWN = 0
NM_STATE_ASLEEP = 1
NM_STATE_CONNECTING = 2
NM_STATE_CONNECTED = 3
NM_STATE_DISCONNECTED = 4

NM_DBUS_INTERFACE = "org.freedesktop.NetworkManager"
NM_DBUS_OBJECTPATH = "/org/freedesktop/NetworkManager"
DBUS_UNKNOWN_SERVICE = "org.freedesktop.DBus.Error.ServiceUnknown"
DBUS_INTERFACE_PROPERTIES = DBUS_PROPS_IFACE = "org.freedesktop.DBus.Properties"
NM_DBUS_INTERFACE_DEVICE = NM_DBUS_INTERFACE + ".Device"
NM_DBUS_INTERFACE_ACTIVE_CONNECTION = NM_DBUS_INTERFACE + ".Connection.Active"
NM_DEVICE_WIRED_IFACE = "org.freedesktop.NetworkManager.Device.Wired"


def get_defaultIface():
    # The interface with the default route.
    # Sets self.defaultIface, returns the default interface.
    bus = dbus.SystemBus()
    proxy = bus.get_object(NM_DBUS_INTERFACE, NM_DBUS_OBJECTPATH)
    manager = dbus.Interface(proxy, DBUS_PROPS_IFACE)
    active = manager.Get(NM_DBUS_INTERFACE, "ActiveConnections")
    for iface in active:
            active_proxy = bus.get_object(NM_DBUS_INTERFACE, iface)
            iface_properties = dbus.Interface(active_proxy, DBUS_PROPS_IFACE)
            default = iface_properties.Get(NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Default")
            if default == True:
                    #Note: this may return multiple devices (I don't know when)
                    default = iface_properties.Get(NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Devices")
                    return default[0]
    return False


def ifaceNameToObjPath(path):
    # Hey, we could just use GetDeviceByIpIface() in org.freedesktop.NetworkManager
    bus = dbus.SystemBus()
    proxy = bus.get_object(NM_DBUS_INTERFACE, path)
    properties_iface = dbus.Interface(proxy, DBUS_INTERFACE_PROPERTIES)
    thisname = properties_iface.Get(NM_DBUS_INTERFACE_DEVICE, "Interface")
    return thisname

def ifaceObjPathToName( objpath):
    # Kinda useless, better off using self.name if possible.
    bus = dbus.SystemBus()
    try:
            proxy = bus.get_object(NM_DBUS_INTERFACE, objpath)
            iface = dbus.Interface(proxy, DBUS_INTERFACE_PROPERTIES)
            return iface.Get(NM_DBUS_INTERFACE_DEVICE, "Interface")
    except:
            exit("Object path not found.")

# Get the MAC address for a network device.
def getMacAddress(dev):
    if dev == '' or dev is None:
        return False

    device_props_iface = getDeviceProperties(dev=dev)
    if device_props_iface is None:
        return None

    device_macaddr = None
    try:
        device_macaddr = device_props_iface.Get(NM_DEVICE_WIRED_IFACE, "HwAddress").upper()
    except dbus.exceptions.DBusException as e:
        if e.get_dbus_name() != 'org.freedesktop.DBus.Error.InvalidArgs':
            raise
    return device_macaddr

# Get a D-Bus interface for the specified device's (e.g., eth0) properties.
# If dev=None, return a hash of the form 'hash[dev] = props_iface' that
# contains all device properties for all interfaces that NetworkManager knows
# about.
def getDeviceProperties(dev=None):
    bus = dbus.SystemBus()
    nm = bus.get_object(NM_DBUS_INTERFACE, NM_DBUS_OBJECTPATH)
    devlist = nm.get_dbus_method("GetDevices")()
    all = {}

    for path in devlist:
        device = bus.get_object(NM_DBUS_INTERFACE, path)
        device_props_iface = dbus.Interface(device, DBUS_PROPS_IFACE)

        device_interface = str(device_props_iface.Get(NM_DBUS_INTERFACE_DEVICE, "Interface"))

        if dev is None:
            all[device_interface] = device_props_iface
        elif device_interface == dev:
            return device_props_iface

    if dev is None:
        return all
    else:
        return None

# Get the MAC address for a network device.
def getMacAddress(dev):
    if dev == '' or dev is None:
        return False

    device_props_iface = getDeviceProperties(dev=dev)


    if device_props_iface is None:
        return None

    device_macaddr = device_props_iface.Get(NM_DEVICE_WIRED_IFACE, "HwAddress")
    return device_macaddr.upper()
    
    
def wait_for_network():
    NM_DBUS_INTERFACE = 'org.freedesktop.NetworkManager'
    bus = dbus.SystemBus(mainloop=DBusGMainLoop())

    nm = bus.get_object(NM_DBUS_INTERFACE, '/org/freedesktop/NetworkManager', follow_name_owner_changes=True)

    manager = dbus.Interface(nm, "org.freedesktop.NetworkManager")

    state_method = manager.get_dbus_method('state')

    while True:
        if state_method() == 70:
            print "GLOBALLY CONNECTED"
            break
        time.sleep(4)


